package com.sky.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.BaseException;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrdersService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.*;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class OrdersServiceImpl implements OrdersService {

    @Resource
    private OrdersMapper ordersMapper;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private AddressBookMapper addressBookMapper;

    @Resource
    private ShoppingCartMapper shoppingCartMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    WeChatPayUtil weChatPayUtil;

    @Resource
    private WebSocketServer webSocketServer;

    @Transactional
    @Override
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        Long addressBookId = ordersSubmitDTO.getAddressBookId();

        OrderSubmitVO orderSubmitVO = new OrderSubmitVO();

        if(addressBookId == null) {
            throw new RuntimeException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        AddressBook addressBook = addressBookMapper.getById(addressBookId);
        // 判断是否合法
        if(addressBook == null) {
            throw new RuntimeException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        Long currentId = BaseContext.getCurrentId();
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.list(currentId);
        if(shoppingCarts == null && shoppingCarts.size() == 0) {
            throw new RuntimeException(MessageConstant.SHOPPING_CART_IS_NULL);
        }

        // 准备数据插入导orders表中
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        orders.setStatus(Orders.PENDING_PAYMENT);
        orders.setPhone(addressBook.getPhone());
        orders.setConsignee(addressBook.getConsignee());
        orders.setUserId(currentId);
        orders.setAddressBookId(addressBook.getId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setPayStatus(Orders.UN_PAID);
        orders.setAddress(addressBook.getDetail());

        ordersMapper.save(orders);

        Long ordersId = orders.getId();

        // 插入订单明细数据
        List<OrderDetail> collect = shoppingCarts.stream().map(shoppingCart -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart, orderDetail);
            orderDetail.setOrderId(ordersId);

            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailMapper.saveBatch(collect);

        // 清空购物车
        shoppingCartMapper.clean(currentId);

        orderSubmitVO.setId(ordersId);
        orderSubmitVO.setOrderNumber(orders.getNumber());
        orderSubmitVO.setOrderAmount(orders.getAmount());
        orderSubmitVO.setOrderTime(orders.getOrderTime());

        return orderSubmitVO;
    }

    /**
     * 订单支付
     *
     * @param ordersPaymentDTO
     * @return
     */
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.getById(userId);

        //调用微信支付接口，生成预支付交易单
//        JSONObject jsonObject = weChatPayUtil.pay(
//                ordersPaymentDTO.getOrderNumber(), //商户订单号
//                new BigDecimal(0.01), //支付金额，单位 元
//                "苍穹外卖订单", //商品描述
//                user.getOpenid() //微信用户的openid
//        );
//
//        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
//            throw new OrderBusinessException("该订单已支付");
//        }

//        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
//        vo.setPackageStr(jsonObject.getString("package"));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "ORDERPAID");
        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));

        // 为替代微信支付成功后的数据库订单状态更新
        Integer OrderPaidStatus = Orders.PAID;  // 订单状态为已支付
        Integer OrderStatus = Orders.TO_BE_CONFIRMED;

        LocalDateTime check_out_time = LocalDateTime.now();

        String orderNumber = ordersPaymentDTO.getOrderNumber();

        ordersMapper.updateStatus(OrderStatus, OrderPaidStatus, check_out_time, orderNumber);

        Orders byNumber = ordersMapper.getByNumber(ordersPaymentDTO.getOrderNumber());

        // 通过websocket向客户端浏览器推送消息 type orderId content
        Map map = new HashMap();
        map.put("type", 1);     // 1表示来单提醒， 2表示客户催单
        map.put("orderId", byNumber.getId());
        map.put("content", "订单号：" + byNumber.getNumber());

        String json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(json);

        return vo;
    }

    /**
     * 支付成功，修改订单状态
     *
     * @param outTradeNo
     */
    public void paySuccess(String outTradeNo) {

        // 根据订单号查询订单
        Orders ordersDB = ordersMapper.getByNumber(outTradeNo);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        ordersMapper.update(orders);
    }

    @Override
    public PageResult pageQuery(Integer page, Integer pageSize, Integer status) {
        PageHelper.startPage(page, pageSize);
        Page<Orders> pageInfo = ordersMapper.pageQuery(status, BaseContext.getCurrentId());

        List<OrderVO> collect = pageInfo.stream().map(item -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(item, orderVO);
            Long id = item.getId();
            List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
            orderVO.setOrderDetailList(orderDetailList);
            return orderVO;
        }).collect(Collectors.toList());
        PageResult pageResult = new PageResult();
        pageResult.setTotal(pageInfo.getTotal());
        pageResult.setRecords(collect);

        return pageResult;
    }

    @Override
    public void repetition(Long id) {
        // 实现再来一单
        // 1、查询当前订单的详细信息
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);

        orderDetails.forEach(orderDetail -> {
            ShoppingCart shoppingCart = new ShoppingCart();
            String name = orderDetail.getName();
            Long dishId = orderDetail.getDishId();
            Long setmealId = orderDetail.getSetmealId();
            String dishFlavor = orderDetail.getDishFlavor();
            Integer number = orderDetail.getNumber();
            BigDecimal amount = orderDetail.getAmount();
            String image = orderDetail.getImage();
            shoppingCart.setName(name);
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCart.setDishId(dishId);
            shoppingCart.setSetmealId(setmealId);
            shoppingCart.setDishFlavor(dishFlavor);
            shoppingCart.setNumber(number);
            shoppingCart.setAmount(amount);
            shoppingCart.setImage(image);
            shoppingCart.setCreateTime(LocalDateTime.now());

            shoppingCartMapper.save(shoppingCart);
        });

//        Long currentId = BaseContext.getCurrentId();
//        Orders orders = ordersMapper.getById(id, currentId);
//        Orders newOrders = new Orders();
//        BeanUtils.copyProperties(orders, newOrders);
//        newOrders.setId(null);
//        newOrders.setNumber(String.valueOf(System.currentTimeMillis()));
//        newOrders.setStatus(Orders.PENDING_PAYMENT);
//        newOrders.setPayStatus(Orders.UN_PAID);
//        newOrders.setOrderTime(LocalDateTime.now());
//        newOrders.setCheckoutTime(null);
//        newOrders.setCancelTime(null);
//        newOrders.setEstimatedDeliveryTime(null);
//        newOrders.setDeliveryTime(null);
//        ordersMapper.save(newOrders);
//
//        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
//        List<OrderDetail> collect = orderDetails.stream().map(orderDetail -> {
//            OrderDetail orderDetail1 = new OrderDetail();
//            BeanUtils.copyProperties(orderDetail, orderDetail1);
//            orderDetail1.setId(null);
//            orderDetail1.setOrderId(newOrders.getId());
//            return orderDetail1;
//        }).collect(Collectors.toList());
//        // 保存orderdetail数据
//        orderDetailMapper.saveBatch(collect);
    }

    @Override
    public OrderVO getById(Long id) {
        OrderVO orderVO = new OrderVO();

        Orders orders = ordersMapper.getById(id);
        if(orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        BeanUtils.copyProperties(orders, orderVO);
        Long orderId = orders.getId();
        List<OrderDetail> OrderDetailList = orderDetailMapper.getByOrderId(orderId);

        orderVO.setOrderDetailList(OrderDetailList);

        return orderVO;
    }

    @Override
    public void cancel(Long id) {
        ordersMapper.cancel(id);
    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {

        int page = ordersPageQueryDTO.getPage();
        int pageSize = ordersPageQueryDTO.getPageSize();
        String number = ordersPageQueryDTO.getNumber();
        String phone = ordersPageQueryDTO.getPhone();
        Integer status = ordersPageQueryDTO.getStatus();
        LocalDateTime beginTime = ordersPageQueryDTO.getBeginTime();
        LocalDateTime endTime = ordersPageQueryDTO.getEndTime();
        Long userId = ordersPageQueryDTO.getUserId();

        PageHelper.startPage(page, pageSize);

        Page<Orders> pageInfo = ordersMapper.getByCondition(ordersPageQueryDTO);

        PageResult pageResult = new PageResult();
        pageResult.setTotal(pageInfo.getTotal());
        pageResult.setRecords(pageInfo.getResult());

        return pageResult;
    }

    @Override
    public OrderStatisticsVO overview() {
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        Integer deliveryInProgress = ordersMapper.getDeliveryInProgress();
        Integer confirmedNum = ordersMapper.getConfirmedNum();
        Integer toBeConfirmed = ordersMapper.getToBeConfirmed();
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        orderStatisticsVO.setConfirmed(confirmedNum);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);


        return orderStatisticsVO;
    }

    @Override
    public void rejection(OrdersRejectionDTO ordersRejectionDTO) {

        Long id = ordersRejectionDTO.getId();
        String rejectionReason = ordersRejectionDTO.getRejectionReason();
        if(id == null || !StrUtil.isNotBlank(rejectionReason)) {
            throw new BaseException(MessageConstant.PARAM_ERROR);
        }
        Orders orders = new Orders();
        orders.setId(id);
        orders.setRejectionReason(rejectionReason);
        orders.setStatus(Orders.CANCELLED);
        orders.setPayStatus(Orders.REFUND);
        ordersMapper.update(orders);
    }

    @Override
    public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
        Orders orders = new Orders();
        orders.setId(ordersConfirmDTO.getId());
        orders.setStatus(Orders.CONFIRMED);
        ordersMapper.update(orders);
    }

    @Override
    public void delivery(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        ordersMapper.update(orders);
    }

    @Override
    public void complete(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.COMPLETED);
        ordersMapper.update(orders);
    }

    @Override
    public void reminder(Long id) {
        // 根据id查询订单
        Orders orders = ordersMapper.getById(id);

        // 校验订单是否存在
        if(orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        // WebSocket 推送
        Map map = new HashMap();
        map.put("type", 2);     // 1表示来单提醒， 2表示客户催单
        map.put("orderId", orders.getId());
        map.put("content", "订单号：" + orders.getNumber());

        String json = JSON.toJSONString(map);
        // 通过websocket向客户端浏览器推送消息
        webSocketServer.sendToAllClient(json);
    }

    @Override
    public OrderOverViewVO overviewOrders() {
        LocalDate now = LocalDate.now();
        LocalDateTime begin = LocalDateTime.of(now, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(now, LocalTime.MAX);
        Integer allOrders = ordersMapper.getTodayTotal(begin, end, null);
        Integer deliveredOrders = ordersMapper.getTodayTotal(begin, end, Orders.CONFIRMED);
        Integer completedOrders = ordersMapper.getTodayTotal(begin, end, Orders.COMPLETED);
        Integer cancelledOrders = ordersMapper.getTodayTotal(begin, end, Orders.CANCELLED);
        Integer waitingOrders = ordersMapper.getTodayTotal(begin, end, Orders.TO_BE_CONFIRMED);

        return OrderOverViewVO.builder()
                .allOrders(allOrders)
                .deliveredOrders(deliveredOrders)
                .completedOrders(completedOrders)
                .cancelledOrders(cancelledOrders)
                .waitingOrders(waitingOrders)
                .build();
    }

    @Override
    public BusinessDataVO businessData(LocalDate bg, LocalDate ed) {

        LocalDateTime begin = LocalDateTime.of(bg, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(ed, LocalTime.MAX);

        Map map = new HashMap();
        map.put("begin", begin);
        map.put("end", end);
        Integer newUser = userMapper.countByMap(map);
        if(newUser == null) {
            newUser = 0;
        }
        map.put("status", Orders.COMPLETED);
        Double turnover = ordersMapper.sumByMap(map);
        if(turnover == null) {
            turnover = 0.0;
        }
        Integer validOrderCount = ordersMapper.getTodayTotal(begin, end, Orders.COMPLETED);
        if(validOrderCount == null) {
            validOrderCount = 0;
        }
        Integer total = ordersMapper.getTodayTotal(begin, end, null);
        if(total == null) {
            total = 0;
        }
        Double orderCompletionRate = 0.0;
        if(total != null && total != 0) {
            orderCompletionRate = 1.0 * validOrderCount / total;
        }
        Double unitPrice = 0.0;
        if(validOrderCount != null && validOrderCount != 0) {
            unitPrice = turnover / validOrderCount;
        }


        return BusinessDataVO.builder()
                .turnover(turnover)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .unitPrice(unitPrice)
                .newUsers(newUser)
                .build();
    }


}
